package com.cqjtu.eecs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cqjtu.eecs.entity.*;
import com.cqjtu.eecs.entity.dto.CourseGoalDTO;
import com.cqjtu.eecs.entity.dto.GoalAssessmentLinkDTO;
import com.cqjtu.eecs.entity.dto.PracticeCourseDTO;
import com.cqjtu.eecs.entity.dto.TheoryCourseDTO;
import com.cqjtu.eecs.entity.vo.CourseOutlineVO;
import com.cqjtu.eecs.entity.vo.CourseTypeVo;
import com.cqjtu.eecs.entity.vo.TrainingProjectCourseVO;
import com.cqjtu.eecs.exception.CourseNotExistException;
import com.cqjtu.eecs.exception.NotFoundException;
import com.cqjtu.eecs.mapper.*;
import com.cqjtu.eecs.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqjtu.eecs.utils.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 培养方案-课程 服务实现类
 * </p>
 *
 * @author
 * @since 2022-03-07
 */
@Service
public class ProjectCourseServiceImpl extends ServiceImpl<ProjectCourseMapper, ProjectCourse> implements IProjectCourseService {
    @Autowired
    private IEntryYearService iEntryYearService;
    @Autowired
    private IMajorService majorService;
    @Autowired
    private ICourseService courseService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private IRequirementService requirementService;
    @Autowired
    private CourseGoalMapper courseGoalMapper;
    @Autowired
    private AssessmentLinkMapper assessmentLinkMapper;
    @Autowired
    private CourseGoalAssessMapper courseGoalAssessMapper;
    @Autowired
    private ProjectCourseMapper projectCourseMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private MajorMapper majorMapper;

    /**
     * 获取课程名
     * @param year
     * @param majorCode
     * @return
     */
    @Override
    public List<Course> listProjectCourseByYearAndMajorCode(Integer year, String majorCode) {
        Project project = projectService.getOne(new LambdaQueryWrapper<Project>().eq(Project::getGrade, year).eq(Project::getMajorCode, majorCode));
        Assert.notNull(project, new NotFoundException("Not find the project"));
        List<ProjectCourse> projectCourses = projectCourseMapper.selectList(new LambdaQueryWrapper<ProjectCourse>().eq(ProjectCourse::getPid, project.getPid()));
        if (projectCourses.isEmpty()){
            return new ArrayList<Course>();
        }
        Set<Integer> collect = projectCourses.stream().map(ProjectCourse::getCourseId).collect(Collectors.toSet());
        List<Course> courseList = courseMapper.listCourseByIdList(new ArrayList<>(collect));
        return courseList;
    }

    /**
     * 获取课程教学大纲
     * @param year 年级
     * @param majorCode 专业代码
     * @param name  课程名
     * @return
     */
    @Override
    public CourseOutlineVO getCourseOutline(Integer year, String majorCode, String name) {
        EntryYear entryYear = iEntryYearService.getById(year);
        Assert.notNull(entryYear, new NotFoundException("Not find the year"));
        Major major = majorService.getById(majorCode);
        Assert.notNull(major, new NotFoundException("Not find the major"));
        Course course = courseService.selectCourseByCourseName(name);
        Assert.notNull(course, new NotFoundException("Not find the course"));
        CourseOutlineVO courseOutlineVO = new CourseOutlineVO();
        // 1.课程简介
        // 查询对应的培养方案
        Project project = projectService.getOne(new LambdaQueryWrapper<Project>()
                .eq(Project::getMajorCode, major.getMajorCode())
                .eq(Project::getGrade, entryYear.getGrade())
        );
        Assert.notNull(project, new NotFoundException("Not find the project"));
        ProjectCourse projectCourse = this.getOne(new LambdaQueryWrapper<ProjectCourse>()
                .eq(ProjectCourse::getCourseId, course.getCourseId())
                .eq(ProjectCourse::getPid, project.getPid())
        );
        Assert.notNull(projectCourse, new NotFoundException("Not find the projectCourse"));
        courseOutlineVO.setTheoryCourseDTO(
                new TheoryCourseDTO(
                        projectCourse.getCourseCode(),
                        course.getCourseName(),
                        projectCourse.getCourseProperty(),
                        projectCourse.getCredit(),
                        projectCourse.getPeriod(),
                        projectCourse.getTheoryPeriod(),
                        projectCourse.getPracticalPeriod(),
                        projectCourse.getComputerPeriod(),
                        projectCourse.getExpeirmentPeriod(),
                        projectCourse.getTerm(),
                        projectCourse.getEvaluationMode()
                )
        );
        // 2.课程目标
        List<CourseGoalDTO> courseGoalDTOS = new ArrayList<>();
        courseOutlineVO.setCourseGoalDTOS(courseGoalDTOS);
        // 获取课程目标
        List<CourseGoal> courseGoals = courseGoalMapper.selectList(new LambdaQueryWrapper<CourseGoal>()
                .eq(CourseGoal::getProjectCourseId, projectCourse.getProjectCourseId()));
        if (courseGoals.isEmpty())
            throw new NotFoundException("Not find the goal");

        List<Requirement> requirements = requirementService
                .list(new LambdaQueryWrapper<Requirement>().eq(Requirement::getPid, project.getPid()));
        Map<Integer, String> requirementIdToCode = requirements.stream()
                .collect(Collectors.toMap(Requirement::getRequirementId, Requirement::getRequirementCode));
        Map<Integer, String> requirementIdToDesc = requirements.stream()
                .collect(Collectors.toMap(Requirement::getRequirementId, Requirement::getRequirementDesc));
        courseGoals.forEach(item->{
            courseGoalDTOS.add(new CourseGoalDTO(
                    item.getCourseGoalName(),
                    item.getCourseGoalDesc(),
                    requirementIdToCode.get(item.getRequirementId()),
                    requirementIdToDesc.get(item.getRequirementId()),
                    item.getWeight()
            ));
        });
        // 3.考核环节
        List<String> assessmentLinks = new ArrayList<>();
        courseOutlineVO.setAssessmentLinks(assessmentLinks);
        // 获取考核环节
        List<AssessmentLink> assessmentLinkList = assessmentLinkMapper.selectList(new LambdaQueryWrapper<AssessmentLink>()
                .eq(AssessmentLink::getProjectCourseId, projectCourse.getProjectCourseId()));
        if (assessmentLinkList.isEmpty())
            throw new NotFoundException("Not find the assessmentLink");
        assessmentLinkList.forEach(item->{
            assessmentLinks.add(item.getLinkName()+"("+((int)(item.getLinkWeight()*100))+"%)");
        });
        Map<Integer, String> collect = assessmentLinkList.stream()
                .collect(Collectors.toMap(AssessmentLink::getLinkId, AssessmentLink::getLinkName));
        // 4.目标-环节支撑矩阵
        List<GoalAssessmentLinkDTO> goalAssessmentLinkDTOS = new ArrayList<>();
        courseOutlineVO.setGoalAssessmentLinkDTOS(goalAssessmentLinkDTOS);
        List<CourseGoalAssess> courseGoalAssesses = courseGoalAssessMapper.selectByIdList(
                assessmentLinkList.stream()
                        .map(AssessmentLink::getLinkId).collect(Collectors.toList()));
        courseGoals.forEach(item->{
            HashMap<String, Float> stringFloatHashMap = new HashMap<>();
            courseGoalAssesses.forEach(it->{
                if (it.getCourseGoalId().equals(item.getCourseGoalId())){
                    // 找到则加入
                    stringFloatHashMap.put(collect.get(it.getLinkId()), it.getWeight());
                }
            });
//            System.out.println(stringFloatHashMap.hashCode());
            goalAssessmentLinkDTOS.add(new GoalAssessmentLinkDTO(
                    item.getCourseGoalName()+":"+item.getCourseGoalDesc(),
                    stringFloatHashMap
            ));
        });
        return courseOutlineVO;
    }


    @Override
    public TrainingProjectCourseVO getTrainingProjectCourseVOByPid(String pid) {
        List<ProjectCourse> projectCourses = projectCourseMapper.selectList(new LambdaQueryWrapper<ProjectCourse>()
                .eq(ProjectCourse::getPid, pid));
        if (projectCourses.isEmpty())
            throw new NotFoundException("不存在对应课程模板或专业");

        try {
            TrainingProjectCourseVO trainingProjectCourseVO = new TrainingProjectCourseVO();

            // 通过专业代码获取专业理论课程
            List<CourseTypeVo> courseTypeList = projectCourseMapper.getTheoryCourseByMajorCode(pid);
            trainingProjectCourseVO.setTheoryCourseList(courseTypeList);
            return trainingProjectCourseVO;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public TrainingProjectCourseVO getPracticalCourseListByPid(String pid) {
        List<ProjectCourse> projectCourses = projectCourseMapper.selectList(new LambdaQueryWrapper<ProjectCourse>()
                .eq(ProjectCourse::getPid, pid));
        if (projectCourses.isEmpty())
            throw new NotFoundException("不存在对应课程模板或专业");

        try {
            TrainingProjectCourseVO trainingProjectCourseVO = new TrainingProjectCourseVO();

            // 通过专业代码获取专业实践课程
            List<PracticeCourseDTO> practiceCourseList = projectCourseMapper.getPracticeCourseByMajorCode(pid);
            trainingProjectCourseVO.setPracticeCourseList(practiceCourseList);
            return trainingProjectCourseVO;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取方案-课程编号
     * @param grade 年级
     * @param majorName 专业名
     * @param courseName   课程名
     * @return
     */
    @Override
    public Integer getProjectCourseId(Integer grade, String majorName, String courseName) {
        // 根据课程名获取课程id
        Course course = courseMapper.selectOne(new QueryWrapper<Course>().eq("course_name", courseName));
        if (course == null)
            throw new CourseNotExistException("课程" + courseName + "不存在");

        // 根据专业名获取专业信息
        Major major = majorMapper.selectOne(new QueryWrapper<Major>().eq("major_name", majorName));
        if (major == null)
            throw new NotFoundException("专业" + majorName + "不存在");

        // 根据年级 专业代码 课程代码获取 方案-课程编号
        Integer id = projectCourseMapper.getId(grade, major.getMajorCode(), course.getCourseId());
        if (id == null)
            throw new CourseNotExistException("课程" + courseName + "在培养方案中不存在");
        return id;
    }

}
